Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - [C#] Consumo eccessivo della ram con le librerie aforce.video
Forum - C# / VB.NET - [C#] Consumo eccessivo della ram con le librerie aforce.video

Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 19:14
Sabato, 03/09/2011
Salve, oggi mi sono trovato a dover sviluppare in c# un applicazione che sfrutta le librerie aforce.video per acquisire immagini da una webcam. Il programma, molto semplice non ha dato particolari problemi finche non mi sono accorto che riempie eccessivamente la ram senza svuotarla, mi spiego meglio, all'avio dell'applicazione essa consuma circa 5mb di ram ma da quando inizia ad acquisire immagini e a visualizzarle in un picurebox il consumo di ram va aumentando di circa 30mb ogni secondo. Ho cercato in rete e dopo aver testato applicazioni simili alla mia mi sono accorto che anche queste presentano lo stesso problema.
Suppongo che quei 30 mb siano dati dalle immagini che vengono inserite nel picturebox e che al cambiare di esso non vengono eliminate dalla memoria, rimanendo come un peso morto in quanto non verranno più utilizzate.
Mi potreste spiegare come eliminare questi dati obsoleti.
Vi incollo le parti principali del codice che ho usato
Codice sorgente - presumibilmente C#

  1. public partial class FormWebcamFtp : Form
  2.     {
  3.         private FilterInfoCollection VideoCaptureDevices;
  4.         private VideoCaptureDevice FinalVideo = null;
  5.  
  6.         public FormWebcamFtp()
  7.         {
  8.             InitializeComponent();
  9.            
  10.             VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
  11.             if (VideoCaptureDevices.Count != 0)
  12.             {
  13.                 foreach (FilterInfo VideoCaptureDevice in VideoCaptureDevices)
  14.                 {
  15.                     DevicesList.Items.Add(VideoCaptureDevice.Name);
  16.                 }
  17.                 DevicesList.SelectedIndex = 0;
  18.                 try
  19.                 {
  20.                     FinalVideo = new VideoCaptureDevice(VideoCaptureDevices[DevicesList.SelectedIndex].MonikerString);
  21.                     FinalVideo.NewFrame += new NewFrameEventHandler(NewFrame);
  22.                     FinalVideo.Start();
  23.                     TimerFps.Enabled = true;
  24.                 }
  25.                 catch (Exception ex)
  26.                 {
  27.                     MessageBox.Show("Errore: " + ex);
  28.                 }
  29.             }
  30.             else
  31.             {
  32.                 DevicesList.Items.Add("(Nessun dispositivo video trovato)");
  33.                 DevicesList.Enabled = false;
  34.             }
  35.         }
  36. (...)
  37.        
  38.         void NewFrame(object sender, NewFrameEventArgs eventArgs)
  39.         {
  40.             WebcamFrame.Dispose();
  41.             WebcamFrame.Image = (Bitmap)eventArgs.Frame.Clone();
  42.         }
  43.         private void FormWebcamFtp_FormClosed(object sender, FormClosedEventArgs e)
  44.         {
  45.             if (FinalVideo != null)
  46.             {
  47.                 if (FinalVideo.IsRunning)
  48.                 {
  49.                     TimerFps.Enabled = false;
  50.                     FinalVideo.SignalToStop();
  51.                     FinalVideo = null;
  52.                 }
  53.             }
  54.         }
  55. (...)


Grazie in anticipo ^^

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 20:07
Sabato, 03/09/2011
Codice sorgente - presumibilmente C# / VB.NET

  1. void NewFrame(object sender, NewFrameEventArgs eventArgs)
  2.         {
  3.             WebcamFrame.Dispose();
  4.             WebcamFrame.Image = (Bitmap)eventArgs.Frame.Clone();
  5.         }



Perchè chiami Clone()?


Il mio blog: https://piero.dev
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 21:08
Sabato, 03/09/2011
è la prima volta che uso le librerie aforge per questo scopo, l'ho messo perchè le guide che ho trovato in rete usavano clone, non sapevo che fosse quello la causa del problema. con cosa lo posso sostituire?

Edit:
Dispose nel codice he ho adesso non c'è più, era solo una prova per risolvere il problema

Ultima modifica effettuata da Roby94 il 03/09/2011 alle 21:10
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 21:17
Sabato, 03/09/2011
Codice sorgente - presumibilmente C# / VB.NET

  1. void NewFrame(object sender, NewFrameEventArgs eventArgs)
  2.         {
  3.             WebcamFrame.Image = (Bitmap)eventArgs.Frame;
  4.         }



Penso dovrebbe andare. Clone() crea una copia dell'oggetto su cui viene chiamato. Ovviamente devi leggere la documentazione di AForge e assicurarti che ci pensi la libreria a chiamare dispose alla ricezione del frame successivo. Altrimenti dovrai scrivere tu il codice che si occupa di eliminare il frame precedente. Qualcosa del genere:

Codice sorgente - presumibilmente C# / VB.NET

  1. if (WebCamFrame.Image != null) WebCamFrame.Image.Dispose();
  2. WebCamFrame.Image = (Bitmap)eventArgs.Frame;



Gli oggetti Bitmap devono essere sempre eliminati esplicitamente; è uno di quei casi in cui il garbage collection del .NET non ti è d'aiuto.


Il mio blog: https://piero.dev
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 21:25
Sabato, 03/09/2011
Ok credo di aver capito, però lasciando perdere un attimo la questione della ram, se tolgo Clone() viene visualizzata un immagine bianca con una X rossa e mi restituisce anche un eccezione non gestita nell'applicazione:
Codice sorgente - presumibilmente VB.NET

  1. Le informazioni su come richiamare il debug JIT (Just-In-Time) anziché questa finestra
  2. sono riportate in fondo al messaggio.
  3.  
  4. ************** Testo dell'eccezione **************
  5. System.ArgumentException: Parametro non valido.
  6.    in System.Drawing.Image.get_Width()
  7.    in System.Drawing.Image.get_Size()
  8.    in System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
  9.    in System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
  10.    in System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
  11.    in System.Windows.Forms.Control.WmPaint(Message& m)
  12.    in System.Windows.Forms.Control.WndProc(Message& m)
  13.    in System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
  14.    in System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
  15.    in System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 21:30
Sabato, 03/09/2011
Devi leggere la documentazione di AForge. E' probabile che la libreria faccia il dispose di ogni frame dopo aver scatenato l'evento NewFrame. In quel caso devi usare Clone() per farti una copia locale, ma devi ricordarti di chiamare Dispose() non appena hai terminato di usarla.


Il mio blog: https://piero.dev
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 21:36
Sabato, 03/09/2011
Grazie mille Piero, ho rimesso clone e fatto il dispose come mi hai fatto vedere tu e adesso il consumo non supera i 14mb, la tua teoria si è rivelata esatta, aforce effetua il dispose gia per conto suo.
Grazie ancora ^^

PM Quote